package com.zhengxing.jienci.user.service.rbac.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.zhengxing.jienci.user.domain.rbac.UserRole;
import com.zhengxing.jienci.common.util.IdGenerateUtil;
import com.zhengxing.jienci.user.mapper.rbac.UserRoleMapper;
import com.zhengxing.jienci.user.service.rbac.UserRoleService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * UserRoleServiceImpl
 *
 * @author philbert
 * @version 1.00
 */
@Slf4j
@Service
@Transactional
@Lazy
public class UserRoleServiceImpl extends ServiceImpl<UserRoleMapper, UserRole> implements UserRoleService {

    @Autowired
    private UserRoleMapper userRoleMapper;

    /**
     * 保存用户角色
     *
     * @param userId  用户主键
     * @param roleIds 角色主键数组
     */
    @Override
    public void save(String userId, String[] roleIds) {
        this.deleteByUserIds(Lists.newArrayList(userId));

        if (roleIds != null && roleIds.length > 0) {
            List<UserRole> userRoles = new ArrayList<>();
            for (String roleId : roleIds) {
                UserRole userRole = new UserRole();
                userRole.setUserId(userId);
                userRole.setRoleId(roleId);
                if (StringUtils.isBlank(userRole.getId())) userRole.setId(IdGenerateUtil.getId());
                if (userRole.getCreatedAt() == null) userRole.setCreatedAt(System.currentTimeMillis());
                userRoles.add(userRole);
            }

            super.saveBatch(userRoles, 100);
        }
    }

    /**
     * 批量保存用户角色
     *
     * @param userRoles 用户角色集合
     */
    @Override
    public void saveBatch(List<UserRole> userRoles) {
        userRoles.parallelStream().forEach(UserRole -> {
            if (StringUtils.isBlank(UserRole.getId())) UserRole.setId(IdGenerateUtil.getId());
            if (UserRole.getCreatedAt() == null) UserRole.setCreatedAt(System.currentTimeMillis());
        });

        super.saveBatch(userRoles, 100);
    }

    /**
     * 根据用户主键集合删除用户角色
     *
     * @param userIds 用户主键集合
     */
    @Override
    public void deleteByUserIds(Collection<String> userIds) {
        LambdaUpdateWrapper<UserRole> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        if (!userIds.isEmpty()) {
            if (userIds.size() == 1)
                userIds.forEach(userId -> lambdaUpdateWrapper.eq(UserRole::getUserId, userId));
            else
                lambdaUpdateWrapper.in(UserRole::getUserId, userIds);

            userRoleMapper.delete(lambdaUpdateWrapper);
        }
    }

    /**
     * 根据角色主键集合删除用户机构
     *
     * @param roleIds 角色主键集合
     */
    @Override
    public void deleteByRoleIds(Collection<String> roleIds) {
        LambdaUpdateWrapper<UserRole> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        if (!roleIds.isEmpty()) {
            if (roleIds.size() == 1)
                roleIds.forEach(roleId -> lambdaUpdateWrapper.eq(UserRole::getRoleId, roleId));
            else
                lambdaUpdateWrapper.in(UserRole::getRoleId, roleIds);

            userRoleMapper.delete(lambdaUpdateWrapper);
        }
    }

    /**
     * 通过用户主键查询该用户所属的所有角色
     *
     * @param userId 用户主键
     * @return 该用户所属的所有角色
     */
    @Override
    @Transactional(readOnly = true)
    public List<UserRole> findByUserId(String userId) {
        SFunction<UserRole, String> sFunction = UserRole::getUserId;
        return findByProp(sFunction, userId);
    }

    /**
     * 通过角色主键查询该角色所有的用户
     *
     * @param roleId 角色主键
     * @return 该角色所有的用户
     */
    @Override
    @Transactional(readOnly = true)
    public List<UserRole> findByRoleId(String roleId) {
        SFunction<UserRole, String> sFunction = UserRole::getRoleId;
        return findByProp(sFunction, roleId);
    }

    private List<UserRole> findByProp(SFunction<UserRole, String> sFunction, String propValue) {
        LambdaQueryWrapper<UserRole> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(sFunction, propValue);
        return userRoleMapper.selectList(lambdaQueryWrapper);
    }

}
